
/* <<< COPYRIGHT START >>>
 * Copyright 2006-Present OxygenSoftwareLibrary.com
 * Licensed under the GNU Lesser General Public License.
 * http://www.gnu.org/licenses/lgpl.html
 * 
 * @author: Ugorji Dick-Nwoke
 * <<< COPYRIGHT END >>>
 */


package oxygen.tool.classcompatibilityinspector;

import java.io.DataInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * This class is not thread safe.
 * To ensure thread-safety, please synchronize access to the instance 
 * before calling the method: introspectClassAndGetReferencedAPIs
 */
public class CCIIntrospector {
  private static String[] EMPTY_STRING_ARRAY = new String[0];
  
  private MyCCIParser parser;
  private Pattern[] pMatchOneOf = null;
  private Pattern[] pMatchNoneOf = null;
  private ArrayList matches = new ArrayList();
  
  public CCIIntrospector(String[] matchOneOf, String[] matchNoneOf) {
    pMatchOneOf = new Pattern[matchOneOf.length];
    pMatchNoneOf = new Pattern[matchNoneOf.length];
    for(int i = 0; i < pMatchOneOf.length; i++) {
      pMatchOneOf[i] = Pattern.compile(matchOneOf[i]);
    }
    for(int i = 0; i < pMatchNoneOf.length; i++) {
      pMatchNoneOf[i] = Pattern.compile(matchNoneOf[i]);
    }
  }
  
  /**
   * Takes an inputstream (a class) and a list of prefixes to look for
   * and returns an array containing all the API's called in that file
   * which begin with any of those prefixes
   */
  public String[] introspectClassAndGetReferencedAPIs(InputStream is) throws Exception {
    matches.clear();
    parser.parse(new DataInputStream(is));
    return (String[])matches.toArray(EMPTY_STRING_ARRAY);
  }
  
  private class MyCCIParser extends CCIParser {
    public void ref(String classN, String member, String type) {
      if (match(classN)) {
        matches.add(new CCIClassMarshaller(classN, member, type).asApiDoc());
      }
    }
    private boolean match(String c) {
      // convert internal to external representation
      c = c.replace('/', '.').replace('$', '.');
      for(int i = 0; i < pMatchNoneOf.length; i++) {
        Matcher m = pMatchNoneOf[i].matcher(c);
        if(m.matches()) {
          return false;
        }
      }
      for(int i = 0; i < pMatchOneOf.length; i++) {
        Matcher m = pMatchOneOf[i].matcher(c);
        if(m.matches()) {
          return true;
        }
      }
      return false;
    }
  }
  
  public static void main(String[] args) throws Exception { 
    System.out.println(CCIIntrospector.class.getClassLoader());
    InputStream in = CCIIntrospector.class.getResourceAsStream("CCIIntrospector.class");
    CCIIntrospector ccii = new CCIIntrospector(args, new String[0]);
    String[] result = ccii.introspectClassAndGetReferencedAPIs(in);
    System.out.println(Arrays.asList(result));
  }
  
}


